package com.chiaching.framwork.config;

import com.chiaching.framwork.core.handler.security.SuperMallLoginSuccessHandler;
import com.chiaching.framwork.core.handler.security.SuperMallLogoutHandler;
import com.chiaching.framwork.core.handler.security.SuperMallUserDetailServiceImpl;
import com.chiaching.framwork.core.handler.security.SuperMallUserTokenAuthenticationFilter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;

import javax.annotation.Resource;

/**
 * @author jiajing.he
 * @date 2021/7/20 下午4:30
 */
@Configuration
@ConditionalOnProperty(value = "super.mall.security.enable",matchIfMissing = true,havingValue = "true")
@EnableWebSecurity
public class SuperMallSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private SuperMallUserDetailServiceImpl superMallUserDetailService;
    @Resource
    private SuperMallUserTokenAuthenticationFilter superMallUserTokenAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // 启用跨域拦截处理
                .cors().and()
                // CSRF 防御关闭
                .csrf().disable()
                //检查是否携带身份信息
                .addFilterBefore(superMallUserTokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                //自定义登录认证
                .authenticationProvider(authenticationProvider())
                // 用户会话存储到 redis(addFilterBefore 添加预处理过滤器)，不采取 HTTP SESSION 方式
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                //访问"/"和"/home"路径的请求 允许角色admin
                .antMatchers("/").hasRole("admin")
                //TODO 可能会被外部模拟获取数据 这样的方式还是不安全
                .antMatchers("/ums/security/*").permitAll()
                //而其他的请求都需要认证
                .anyRequest()
                .authenticated()
                .and()
                //修改Spring Security默认的登陆界面
                .formLogin()
                //登录成功处理器
                .successHandler(authenticationSuccessHandler())
                //.loginPage("/login")
                .permitAll()
                .and()
                .logout()
                //登出处理器
                .addLogoutHandler(logoutHandler())
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }

    @Bean
    public AuthenticationProvider authenticationProvider(){
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setUserDetailsService(superMallUserDetailService);
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        return daoAuthenticationProvider;
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
        //明文
        //return NoOpPasswordEncoder.getInstance();
    }

    @Bean
    public LogoutHandler logoutHandler(){
        return new SuperMallLogoutHandler();
    }

    @Bean
    public AuthenticationSuccessHandler authenticationSuccessHandler(){
        return new SuperMallLoginSuccessHandler();
    }
}
